package com.opennews.openplatform.familyexpenseapi.security

import com.opennews.openplatform.familyexpenseapi.entity.Tables.USER_ACTIVE_TOKEN
import com.opennews.openplatform.myspringbootcore.dto.ActiveToken
import com.opennews.openplatform.myspringbootcore.security.ActiveTokenManager
import com.opennews.openplatform.myspringbootcore.util.DateHelper
import org.jooq.DSLContext
import org.springframework.stereotype.Component

@Component
class SecurityActiveTokenManager(
    private val dslContext: DSLContext,
) : ActiveTokenManager {
    companion object {
        // It only caches access tokens since refresh tokens never expire.
        // By using cached access tokens would reduce access to database.
        private var localCachedUserActiveTokens: List<ActiveToken>? = null
    }

    override fun isActiveAccessToken(username: String, deviceId: String?, accessToken: String): Boolean {
        // Checks from Redis
        //        String cachedUsername = redisTemplate.opsForValue().get(accessToken);
        //
        //        return cachedUsername != null && cachedUsername.equals(username);

        return getCachedUserActiveTokens().any {
            it.username == username
                    && it.deviceId == deviceId
                    && it.accessToken == accessToken
        }
    }

    override fun getCachedUserActiveTokens(): List<ActiveToken> {
        if (localCachedUserActiveTokens == null) {
            reloadCachedUserActiveTokenRecords()
        }

        return localCachedUserActiveTokens!!
    }

    override fun reloadCachedUserActiveTokenRecords() {
        localCachedUserActiveTokens = dslContext
            .selectFrom(USER_ACTIVE_TOKEN)
            .where(
                USER_ACTIVE_TOKEN.DATE_EXPIRED.ge(DateHelper.getCurrentLocalDateTime())
                    .and(USER_ACTIVE_TOKEN.ENABLED.isTrue())
            )
            .fetch()
            .map { record ->
                ActiveToken(
                    username = record.username,
                    deviceId = record.deviceId,
                    accessToken = record.accessToken,
                )
            }
    }
}